package com.litidea.filters;

import static com.litidea.commons.keys.SystemKeys.USER_LOGIN_DO;
import static com.litidea.commons.tools.ConvertPassword.getLoginUserConvert;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.litidea.commons.keys.SystemKeys;
import com.litidea.dao.SystemDAO;
import com.litidea.dataobjects.MenuNodeDO;
import com.litidea.dataobjects.UserDO;
import com.litidea.dataobjects.UserLoginDO;

public class PubFilter implements Filter {
	
	private Log logger = LogFactory.getLog(PubFilter.class);
	
	private final static String LOGIN_FILE = "/login.jsp";
	
	private final static String LOGIN_ACTION = "/login/";
	
	private final static String PASSWORD = "password";
	
	private final static String USERNAME = "username";
	
	private final static String LOGIN_CONVERT_NAME = "loginConvertName";
	
	private WebApplicationContext application;
	
	private String contextPath;
	
	private static FilterProcessor processor;
	
	private byte[]loginNoInputFailResponse = null;
	
	private byte[]loginNoUserFailResponse = null;
	
	private byte[]loginFailPasswordResponse = null;
	
	//private byte[]loginSuccessResponse = null;
	
	public void init(FilterConfig filterConfig) throws ServletException {
		contextPath = filterConfig.getServletContext().getContextPath();
		MenuNodeDO.init(contextPath);
		application = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
		processor = new FilterProcessor((SystemDAO)application.getBean("systemDAO"));
		try {
			loginNoInputFailResponse = "{\"loginstatus\":\"0\",\"msg\":\"用户名或密码为空，请输入后提交。\"}".getBytes("UTF-8");
			loginNoUserFailResponse = "{\"loginstatus\":\"0\",\"msg\":\"对不起，没有找到该用户信息。\"}".getBytes("UTF-8");
			loginFailPasswordResponse = "{\"loginstatus\":\"0\",\"msg\":\"密码错误，请从新输入后提交。\"}".getBytes("UTF-8");
			//loginSuccessResponse = "{\"loginstatus\":\"1\",\"msg\":\"\"}".getBytes("UTF-8");
			logger.info("init PubFilter success...");
		}catch(Exception e) {
			logger.error("when init info error" , e);
		}
	}
    
    /**
     * 过滤器执行部分
     * @param request
     * @param response
     * @param chain
     * @throws java.io.IOException
     * @throws ServletException
     */
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
    	//request.setCharacterEncoding(SystemKeys.REQUEST_CHARSET);
    	HttpServletRequest req = (HttpServletRequest)request;
    	String requestUri = req.getServletPath();
    	if(requestUri.endsWith(".css") || requestUri.endsWith(".js") 
    			|| requestUri.endsWith(".png")
    			|| requestUri.endsWith(".jpg")
    			|| requestUri.endsWith(".gif")
    			|| requestUri.endsWith(".jpep")
    			|| requestUri.endsWith(".ico")
    			|| requestUri.startsWith("/services")) {//静态资源
    		chain.doFilter(request, response);
    	}else {
    		boolean isLoginFile = requestUri.equals(LOGIN_FILE);
    		String loginConvertName = getLoginId(req);
    		if(isLoginFile) {//退出操作
    			if("true".equals(request.getParameter("loginout"))) {
    				userLoginOut(request, response, loginConvertName);
    			}else {
    				chain.doFilter(request, response);
    			}
    		}else {//其他操作
    			if(StringUtils.isEmpty(loginConvertName) 
    					|| processor.isExpired(loginConvertName)) {//没有cookie key，或缓存过期
    				noCookNeedLogin(request, response, req, requestUri);
    			}else {
    				preToLoginIn(request, response, chain, loginConvertName);
    			}
    		}
    	}
    }

    /**
     * 最后准备登录
     * @param request
     * @param response
     * @param chain
     * @param loginConvertName
     * @throws ServletException
     * @throws IOException
     */
	private void preToLoginIn(ServletRequest request, ServletResponse response,
			FilterChain chain, String loginConvertName)
			throws ServletException, IOException {
		UserLoginDO userLoginDO = processor.getMemUser(loginConvertName);
		if(userLoginDO == null) {
			delUserCookie(response);
			toLoginPage(request , response);
		}else {
			loginSuccess(request, response, chain , userLoginDO);
		}
	}

    /**
     * 没有cookie需要选择登录
     * @param request
     * @param response
     * @param req
     * @param requestUri
     * @throws ServletException
     * @throws IOException
     */
	private void noCookNeedLogin(ServletRequest request,
			ServletResponse response, HttpServletRequest req, String requestUri)
			throws ServletException, IOException {
		//没有cookie信息
		String userName = req.getParameter(USERNAME);
		String password = req.getParameter(PASSWORD);
		if(userName == null || password == null) {
			if(LOGIN_ACTION.equals(requestUri)) {//用来登录，返回登录失败
				loginResponse(response , loginNoInputFailResponse);
			}else {//跳转到登陆页面
				toLoginPage(request , response);
			}
		}else {
			UserDO userDO = processor.getUserByLoginName(userName);
			if(userDO == null) {
				loginResponse(response , loginNoUserFailResponse);
			}else {
				if(!FilterProcessor.checkPassword(password, userDO)) {
					loginResponse(response , loginFailPasswordResponse);
				}else {
					loginSuccess(response, userName, userDO , req.getRemoteAddr());
				}
			}
		}
	}

    /**
     * 用户手工点击退出
     * @param request
     * @param response
     * @param loginConvertName
     * @throws ServletException
     * @throws IOException
     */
	private void userLoginOut(ServletRequest request, ServletResponse response,
			String loginConvertName) throws ServletException, IOException {
		delUserCookie(response);
		if(loginConvertName != null) 
			processor.loginOut(loginConvertName, FilterProcessor.USER_LOGIN_OUT);
		toLoginPage(request , response);
	}
    
    /**
     * 用户cookie
     * @param response
     * @param userName
     */
    private void delUserCookie(ServletResponse response) {
    	Cookie namecookie = new Cookie(LOGIN_CONVERT_NAME , null);
    	namecookie.setMaxAge(-1);
    	HttpServletResponse resp = (HttpServletResponse)response;
    	resp.addCookie(namecookie);
    }

    /**
     * 登录成功
     * @param response
     * @param userName
     * @param userDO
     */
	private void loginSuccess(ServletResponse response, String userName,
			UserDO userDO , String ip) {
		//写缓存、写登陆日志、写用户最后登录时间
		String key = getLoginUserConvert(userName);
		//addCookie(response , key);
		processor.addUserCache(key, userDO , ip);
		JSONObject object = new JSONObject();
		object.put("loginstatus", "1");
		object.put("msg", "login success");
		object.put("cookieName", LOGIN_CONVERT_NAME);
		object.put("cookieValue", key);
		try {
			loginResponse(response , object.toString().getBytes("GBK"));
		}catch(Exception e) {
			logger.error("when response login success error" , e);
		}
	}
    
    /**
     * 登录输出信息
     * @param response
     * @param responseContent
     */
    private void loginResponse(ServletResponse response , byte[]responseContent) {
    	try {
    		response.setContentType(SystemKeys.SYSTEM_JSON_CONTENT);
    		ServletOutputStream out = response.getOutputStream();
			out.write(responseContent);
			out.flush();
    	}catch(Exception e) {
    		
    	}
    }

    /**
     * 登录成功需要的操作
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
	private void loginSuccess(ServletRequest request, ServletResponse response,
			FilterChain chain , UserLoginDO userLoginDO) throws IOException, ServletException {
		request.setAttribute(USER_LOGIN_DO, userLoginDO);
		response.setContentType(SystemKeys.SYSTEM_DEFAULT_CONTENT);
		request.getParameterMap();
		chain.doFilter(request, response);
	}
    
    /**
     * 获取login的ID信息
     * @param request
     * @return
     */
    private String getLoginId(HttpServletRequest request) {
    	Cookie []cookies = request.getCookies();
    	if(cookies == null) return null;
    	String tempValue = null;
    	for(Cookie cookie : cookies) {
    		if(LOGIN_CONVERT_NAME.equals(cookie.getName()))
    			tempValue = cookie.getValue();
    	}
    	return tempValue;
    }
    
    /**
     * 跳转到登陆界面
     */
    private void toLoginPage(ServletRequest request, ServletResponse response)
			throws ServletException, IOException {
    	/*String path = ((HttpServletRequest)request).getContextPath() + "/";
    	((HttpServletResponse)response).sendRedirect(path);*/
		RequestDispatcher dispatcher = request.getRequestDispatcher(LOGIN_FILE);
		dispatcher.forward(request, response);
		return;
    }
    
    
    public void destroy() {
    	
    }

}
